/**************************************************************
 * @file     adc_product.c
 * @brief    用于通知ADC与DMA转换搬运
 * @author   Ruilist
 * @date     2025-08-03
 * @version  V1.0.0
 * @copyright Copyright (c) 2025
 *
 * @note     1 tab = 4 space
 *
 * @par 日志:
 * - V1.0.0 2025-07-25 Ruilist
 **************************************************************/

//******************************** Includes *********************************//

#include "adc_product.h"

//******************************** Includes *********************************//

//******************************** Defines **********************************//

//******************************** Defines **********************************//

//*********************Thread_Func **********************//

osThreadId_t adc_product_TaskHandle;

const osThreadAttr_t adc_product_attributes = {
    .name       = "adc_product_Task",
    .stack_size = 128 * 4,
    .priority   = (osPriority_t)osPriorityHigh,
};

//*********************Thread_Func **********************//

//*********************Queue_Handler ********************//

QueueHandle_t adc_completed_queue    = NULL;
QueueHandle_t buffer_completed_queue = NULL;

SemaphoreHandle_t xMutex = NULL;

//*********************Queue_Handler ********************//

//******************************** Declaring ********************************//

uint32_t *gp_buffer1    = NULL;
uint32_t *gp_buffer2    = NULL;
uint32_t  buffer_contrl = BUFFER_1;

/**
 * @brief   adc_product任务
 *
 * @param   *argument    任务默认参数
 *
 * @return  空
 *
 */
void adc_product_Task_func( void *argument )
{
    // 初始化buffer空间
    gp_buffer1 = (uint32_t *)malloc( sizeof( uint32_t ) * BUFFER_SIZE );
    gp_buffer2 = (uint32_t *)malloc( sizeof( uint32_t ) * BUFFER_SIZE );

    uint32_t buffer_check = BUFFER_1;  // 初始化第一个buffer存储位置

    if ( NULL == gp_buffer1 )
    {
        log_e( "gp_buffer1 created failed\r\n" );
        return;
    }
    if ( NULL == gp_buffer2 )
    {
        log_e( "gp_buffer2 created failed\r\n" );
        return;
    }
    log_i( "gp_buffer1 and gp_buffer2 created successfully\r\n" );

    memset( gp_buffer1, 1, ( sizeof( uint32_t ) * BUFFER_SIZE ) );
    memset( gp_buffer2, 2, ( sizeof( uint32_t ) * BUFFER_SIZE ) );
    log_i( "gp_buffer1 and gp_buffer2 initialization successfully\r\n" );
    // 完成buffer的初始化

    adc_completed_queue = xQueueCreate( 1, sizeof( uint32_t ) );
    if ( NULL == adc_completed_queue )
    {
        log_e( "adc_completed_queue created failed\r\n" );
    }
    buffer_completed_queue = xQueueCreate( 1, sizeof( uint32_t ) );
    if ( NULL == buffer_completed_queue )
    {
        log_e( "buffer_completed_queue created failed\r\n" );
    }
    // 初始化ADC完成队列与buffer处理完成队列

    // 创建互斥锁
    xMutex = xSemaphoreCreateMutex();
    if ( NULL != xMutex )
    {
        log_i( "xMutex created successfully\r\n" );
    }

    HAL_StatusTypeDef hal_adc_start_dma_ret = HAL_OK;
    hal_adc_start_dma_ret                   = HAL_ADC_Start_DMA( &hadc1, gp_buffer1, BUFFER_SIZE );
    if ( HAL_OK != hal_adc_start_dma_ret )
    {
        log_e( "HAL_ADC_Start_DMA is failed\r\n" );
    }

    for ( ;; )
    {
        // log_i( "adc_product_Task_func start\r\n" );

        // 一旦接收ADC队列消息，就通知consume线程处理数据
        if ( pdTRUE == xQueueReceive( adc_completed_queue, &buffer_check, portMAX_DELAY ) )
        {
            // log_i( "xQueueReceive from adc_completed_queue data is [%d]\r\n", buffer_check );

            // 先查询buffer队列中是否还有数据
            if ( errQUEUE_EMPTY == xQueuePeek( buffer_completed_queue, &buffer_check, 0 ) )
            {
                // 队列中无数据通知consume线程处理
                if ( pdTRUE == xQueueSend( buffer_completed_queue, &buffer_check, 0 ) )
                {
                     log_i( "xQueueSend to buffer_completed_queue data is [%d]\r\n", buffer_check );
                }

                //  队列中无数据可以通知dma向新buffer中存储
                if ( BUFFER_1 == buffer_check )
                {

                    buffer_contrl         = BUFFER_2;
                    hal_adc_start_dma_ret = HAL_ADC_Start_DMA( &hadc1, gp_buffer2, BUFFER_SIZE );
                    if ( HAL_OK != hal_adc_start_dma_ret )
                    {
                        log_e( "HAL_ADC_Start_DMA is failed\r\n" );
                    }
                }
                else if ( BUFFER_2 == buffer_check )
                {
                    buffer_contrl         = BUFFER_1;
                    hal_adc_start_dma_ret = HAL_ADC_Start_DMA( &hadc1, gp_buffer1, BUFFER_SIZE );
                    if ( HAL_OK != hal_adc_start_dma_ret )
                    {
                        log_e( "HAL_ADC_Start_DMA is failed\r\n" );
                    }
                }
            }
            // 如果队列中有数据，说明consume还未处理完，此时product线程尝试获取锁
            else if ( pdTRUE == xQueuePeek( buffer_completed_queue, &buffer_check, 0 ) )
            {
                if ( pdTRUE == xSemaphoreTake( xMutex, portMAX_DELAY ) )
                {
                }
                // 获取到锁说明consume已经处理完，可以释放锁
                if ( pdTRUE != xSemaphoreGive( xMutex ) )
                {
                    log_e( "adc_consume_Task_func xSemaphoreGive is failed\r\n" );
                }
                
                // 队列中无数据通知consume线程处理
                if ( pdTRUE == xQueueSend( buffer_completed_queue, &buffer_check, 0 ) )
                {
                    log_i( "xQueueSend to buffer_completed_queue data is [%d]\r\n", buffer_check );
                }
                //  队列中无数据可以通知dma向新buffer中存储
                if ( BUFFER_1 == buffer_check )
                {

                    buffer_contrl         = BUFFER_2;
                    hal_adc_start_dma_ret = HAL_ADC_Start_DMA( &hadc1, gp_buffer2, BUFFER_SIZE );
                    if ( HAL_OK != hal_adc_start_dma_ret )
                    {
                        log_e( "HAL_ADC_Start_DMA is failed\r\n" );
                    }
                }
                else if ( BUFFER_2 == buffer_check )
                {
                    buffer_contrl         = BUFFER_1;
                    hal_adc_start_dma_ret = HAL_ADC_Start_DMA( &hadc1, gp_buffer1, BUFFER_SIZE );
                    if ( HAL_OK != hal_adc_start_dma_ret )
                    {
                        log_e( "HAL_ADC_Start_DMA is failed\r\n" );
                    }
                }
            }
        }
        osDelay( 1 );
    }
}

/**
 * @brief   ADC转换完成回调函数
 *
 * @param   ADC_HandleTypeDef *hadc    ADC句柄
 *
 * @return  空
 *
 */
void HAL_ADC_ConvCpltCallback( ADC_HandleTypeDef *hadc )
{
    /* Prevent unused argument(s) compilation warning */
    UNUSED( hadc );
    /* NOTE : This function Should not be modified, when the callback is needed,
              the HAL_ADC_ConvCpltCallback could be implemented in the user file
     */
    BaseType_t xHigherPrioritTaskWoken = pdTRUE;

    if ( pdTRUE == xQueueSendFromISR( adc_completed_queue, &buffer_contrl, &xHigherPrioritTaskWoken ) )
    {
        log_i( "xQueueSend to adc_completed_queue data is [%d]\r\n", buffer_contrl );
        //  if ( BUFFER_1 == buffer_contrl )
        //  {
        //      log_i( "adc buffer_1 data is [%d]\r\n", ( *gp_buffer1 ) );
        //  }
        //  else
        //  {
        //      log_i( "adc buffer_2 data is [%d]\r\n", ( *gp_buffer2 ) );
        //  }
    }
    // log_i( "adc transfer successfully\r\n" );
}

/**
 * @brief   ADC转换失败回调函数
 *
 * @param   ADC_HandleTypeDef *hadc    ADC句柄
 *
 * @return  空
 *
 */
void HAL_ADC_ErrorCallback( ADC_HandleTypeDef *hadc )
{
    /* Prevent unused argument(s) compilation warning */
    UNUSED( hadc );
    /* NOTE : This function Should not be modified, when the callback is needed,
              the HAL_ADC_ErrorCallback could be implemented in the user file
     */
    log_e( "adc transfer error\r\n" );
}
//******************************** Declaring ********************************//
